package com.example.verification.demo.common.exception;

import com.example.verification.demo.common.pojo.res.WebResultBean;
import com.example.verification.demo.common.util.Constants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.ServletRequestBindingException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;

import javax.servlet.http.HttpServletRequest;

/**
 * Created by hzy on 2018/9/7.
 */
@RestControllerAdvice
public class GlobalExceptionHandler {
    private static final Logger LOGGER = LoggerFactory.getLogger(GlobalExceptionHandler.class);

    //region 业务异常
    @ExceptionHandler(value = MyException.class)
    public WebResultBean<String> businessExceptionHandler(HttpServletRequest req, MyException e) throws Exception {
        LOGGER.error("businessExceptionHandler()",e);
        WebResultBean<String> webResultBean = new WebResultBean<>();
        //
        switch (e.code){
            case Constants.RespCode.VERIFICATION_FAILED : // token 失效
                webResultBean.code = Constants.RespCode.VERIFICATION_FAILED;
                webResultBean.message = Constants.RespMsg.VERIFICATION_FAILED;
                break;
                default:break;
        }
        return webResultBean;
    }
    //endregion

    //region other exception handling

    /**
     * 处理其他异常
     * @throws Exception
     */
    @ExceptionHandler(value = Exception.class)
    public WebResultBean<String> defaultExceptionHandler(HttpServletRequest req, Exception e) throws Exception {
        LOGGER.error("defaultExceptionHandler()",e);

        WebResultBean<String> webResultBean = new WebResultBean<>();
        webResultBean.code = Constants.RespCode.FAILED;
        webResultBean.message = Constants.RespMsg.FAILED;
        webResultBean.data = e.getMessage();
        return webResultBean;
    }

    //endregion


    //region special handling
//    /**
//     * 处理所有Bean数据验证异常(且包括自定义校验注解)
//     */
//    @ExceptionHandler(MethodArgumentNotValidException.class)
//    public WebResultBean<String> handleMethodArgumentNotValidException(MethodArgumentNotValidException e){
//        LOGGER.error("handleMethodArgumentNotValidException: ",e);
//
//        WebResultBean<String> webResultBean = new WebResultBean<>();
//        webResultBean.code = Constants.RespCode.REQUEST_PARAM_INVALIDATION_FAILED;
//
//        //
//        StringBuilder sb = new StringBuilder();
//        BindingResult bindingResult = e.getBindingResult();
//        if (bindingResult.hasErrors()) {
//            for (ObjectError error : e.getBindingResult().getAllErrors()) {
//                if (error instanceof FieldError){
//                    FieldError fieldError = (FieldError) error;
//                    sb.append(fieldError.getField()).append(" ").append(fieldError.getDefaultMessage()).append(" , ");
//                }else {
//                    sb.append(error.getObjectName()).append(" ").append(error.getDefaultMessage()).append(" , ");
//                }
//            }
//
//            webResultBean.message = sb.delete(sb.length()-3,sb.length()-1).toString(); // 剔除最后一个 " , "
//        }else {
//            webResultBean.message = Constants.RespMsg.REQUEST_PARAM_INVALIDATION_FAILED;
//        }
//        return webResultBean;
//    }
//
//    /**
//     * 请求参数绑定异常(如:HTTP请求中queryString或者pathVariable中的 required==true 的参数未传递)
//     */
//    @ExceptionHandler(ServletRequestBindingException.class)
//    public WebResultBean<String> handleServletRequestBindingException(ServletRequestBindingException e) {
//        LOGGER.error("handleServletRequestBindingException: ", e);
//        //
//        WebResultBean<String> webResultBean = new WebResultBean<>();
//        webResultBean.code = Constants.RespCode.REQUEST_PARAM_INVALIDATION_FAILED;
//        webResultBean.message = e.getMessage();
//        return webResultBean;
//    }
//
//    /**
//     * 处理对于需要携带Body的请求,而客户端发送的Body为null,或者在服务端发生Body解析失败等问题。
//     */
//    @ExceptionHandler(HttpMessageNotReadableException.class)
//    public WebResultBean<String> handleHttpMessageNotReadableException(HttpMessageNotReadableException e){
//        LOGGER.error("handleHttpMessageNotReadableException: ",e);
//        //
//        WebResultBean<String> webResultBean = new WebResultBean<>();
//        // 目前也将 HttpMessageNotReadableException 划定为参数校验问题。
//        webResultBean.code = Constants.RespCode.REQUEST_PARAM_INVALIDATION_FAILED;
//        webResultBean.message = e.getMessage();
//        return webResultBean;
//    }
//
//    /**
//     * 处理 Controller 层的目标方法的参数类型不匹配异常。
//     */
//    @ExceptionHandler(MethodArgumentTypeMismatchException.class)
//    public WebResultBean<String> handleMethodArgumentTypeMismatchException(MethodArgumentTypeMismatchException e){
//        LOGGER.error("handleMethodArgumentTypeMismatchException: ",e);
//        //
//        WebResultBean<String> webResultBean = new WebResultBean<>();
//        webResultBean.code = Constants.RespCode.REQUEST_PARAM_INVALIDATION_FAILED;
//        webResultBean.message = e.getMessage();
//        return webResultBean;
//    }
//
//    /**
//     * 处理HTTP请求方法不支持异常
//     */
//    @ExceptionHandler(value = HttpRequestMethodNotSupportedException.class)
//    public WebResultBean<String> handleHttpRequestMethodNotSupportedException(HttpServletRequest req, HttpRequestMethodNotSupportedException e) {
//        LOGGER.error("httpRequestMethodNotSupportedException: ", e);
//        //
//        WebResultBean<String> webResultBean = new WebResultBean<>();
//        webResultBean.code = Constants.RespCode.REQUEST_METHOD_NOT_SUPPORTED;
//        webResultBean.message = e.getMessage();
//        return webResultBean;
//    }
    //endregion

}
